#!/usr/bin/env python3
"""
多账户交易机器人管理器
支持同时运行多个账户（模拟盘、实盘等）
"""

import os
import json
import time
import threading
import logging
import signal
import sys
from datetime import datetime, timedelta, time as dt_time, date
from typing import Dict, Optional
import ccxt
from concurrent.futures import ThreadPoolExecutor, as_completed

# 导入原有的交易逻辑
from deepseek import (
    execute_trade,
    send_telegram_message,
    analyze_with_deepseek,
    get_ohlcv_enhanced,
    print,
    create_strategy_state,
    StrategyState,
)

# 导入Flight策略
from flight_strategy import (
    analyze_with_flight,
    get_flight_ohlcv_data,
    init_flight_exchange,
    FLIGHT_CONFIG,
)

TRADE_HISTORY_FILE = os.path.join('logs', 'trade_history.jsonl')

class AccountManager:
    """账户管理器"""
    
    def __init__(self, config_file: str = "accounts_config.json"):
        self.config_file = config_file
        self.accounts_config = self.load_config()
        self.active_accounts: Dict[str, 'TradingAccount'] = {}
        self.running = False
        self.executor = ThreadPoolExecutor(max_workers=self.accounts_config['global_settings']['max_concurrent_accounts'])
        
        # 设置信号处理
        signal.signal(signal.SIGINT, self.signal_handler)
        signal.signal(signal.SIGTERM, self.signal_handler)
        
        # 设置主日志
        self.main_logger = self.setup_main_logger()
        self.performance_reporter = PerformanceReporter(self.main_logger)
        
    def load_config(self) -> dict:
        """加载配置文件"""
        try:
            with open(self.config_file, 'r', encoding='utf-8') as f:
                config = json.load(f)
            return config
        except Exception as e:
            print(f"❌ 加载配置文件失败: {e}")
            sys.exit(1)
    
    def setup_main_logger(self):
        """设置主日志"""
        logger = logging.getLogger('account_manager')
        logger.setLevel(logging.INFO)
        
        # 创建日志目录
        os.makedirs('logs', exist_ok=True)
        
        # 文件处理器
        file_handler = logging.handlers.RotatingFileHandler(
            'logs/account_manager.log',
            maxBytes=10*1024*1024,  # 10MB
            backupCount=5,
            encoding='utf-8'
        )
        file_handler.setLevel(logging.INFO)
        
        # 控制台处理器
        console_handler = logging.StreamHandler()
        console_handler.setLevel(logging.INFO)
        
        # 格式化
        formatter = logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
        )
        file_handler.setFormatter(formatter)
        console_handler.setFormatter(formatter)
        
        logger.addHandler(file_handler)
        logger.addHandler(console_handler)
        
        return logger

    def _resolve_env_value(self, placeholder: Optional[str]) -> Optional[str]:
        """解析配置中的环境变量占位符"""
        if not placeholder:
            return None
        key = placeholder.strip('${}')
        value = os.getenv(key)
        if value is None and placeholder == key:
            return placeholder
        return value

    def _build_telegram_runtime_config(self) -> Dict[str, Optional[str]]:
        """解析Telegram配置，返回运行时所需的Token与Chat ID"""
        tele_cfg = self.config.get('telegram', {})
        if not tele_cfg.get('enabled', False):
            return {'enabled': False}

        bot_token = self._resolve_env_value(tele_cfg.get('bot_token'))
        chat_id = self._resolve_env_value(tele_cfg.get('chat_id'))

        if not bot_token or not chat_id:
            self.logger.warning(f"[{self.account_id}] Telegram配置不完整，已禁用通知")
            return {'enabled': False}

        return {
            'enabled': True,
            'bot_token': bot_token,
            'chat_id': chat_id
        }

    def _get_loop_interval(self) -> int:
        """根据配置的时间周期确定循环间隔"""
        if not self.strategy_state:
            return 900

        timeframe = self.strategy_state.trade_config.get('timeframe', '15m')
        try:
            unit = timeframe[-1]
            value = int(timeframe[:-1])
        except (ValueError, IndexError):
            return 900

        unit_map = {
            's': 1,
            'm': 60,
            'h': 3600,
            'd': 86400
        }
        multiplier = unit_map.get(unit, 60)
        interval = value * multiplier
        return max(interval, 30)
    
    def signal_handler(self, signum, frame):
        """信号处理器"""
        self.main_logger.info(f"收到信号 {signum}，正在关闭所有账户...")
        self.stop_all_accounts()
        sys.exit(0)
    
    def start_account(self, account_id: str) -> bool:
        """启动单个账户"""
        try:
            account_config = self.accounts_config['accounts'][account_id]
            
            if not account_config.get('enabled', False):
                self.main_logger.info(f"账户 {account_id} 未启用，跳过")
                return False
            
            # 创建交易账户实例
            account = TradingAccount(account_id, account_config, self.main_logger)
            
            # 启动账户
            if account.start():
                self.active_accounts[account_id] = account
                self.main_logger.info(f"✅ 账户 {account_id} 启动成功")
                return True
            else:
                self.main_logger.error(f"❌ 账户 {account_id} 启动失败")
                return False
                
        except Exception as e:
            self.main_logger.error(f"❌ 启动账户 {account_id} 时出错: {e}")
            return False
    
    def stop_account(self, account_id: str):
        """停止单个账户"""
        if account_id in self.active_accounts:
            account = self.active_accounts[account_id]
            account.stop()
            del self.active_accounts[account_id]
            self.main_logger.info(f"🛑 账户 {account_id} 已停止")
    
    def stop_all_accounts(self):
        """停止所有账户"""
        self.running = False
        
        for account_id in list(self.active_accounts.keys()):
            self.stop_account(account_id)
        
        self.executor.shutdown(wait=True)
        self.main_logger.info("🛑 所有账户已停止")
    
    def start_all_accounts(self):
        """启动所有账户"""
        self.main_logger.info("🚀 开始启动多账户交易系统...")
        
        enabled_accounts = [
            account_id for account_id, config in self.accounts_config['accounts'].items()
            if config.get('enabled', False)
        ]
        
        if not enabled_accounts:
            self.main_logger.warning("⚠️ 没有启用的账户")
            return
        
        self.main_logger.info(f"📊 发现 {len(enabled_accounts)} 个启用的账户: {enabled_accounts}")
        
        # 并发启动所有账户
        futures = []
        for account_id in enabled_accounts:
            future = self.executor.submit(self.start_account, account_id)
            futures.append((account_id, future))
        
        # 等待所有账户启动完成
        for account_id, future in futures:
            try:
                success = future.result(timeout=30)
                if success:
                    self.main_logger.info(f"✅ {account_id} 启动完成")
                else:
                    self.main_logger.error(f"❌ {account_id} 启动失败")
            except Exception as e:
                self.main_logger.error(f"❌ {account_id} 启动异常: {e}")
        
        self.running = True
        self.main_logger.info(f"🎯 多账户系统启动完成，活跃账户: {list(self.active_accounts.keys())}")
    
    def health_check(self):
        """健康检查"""
        while self.running:
            try:
                time.sleep(self.accounts_config['global_settings']['health_check_interval'])
                
                if not self.running:
                    break
                
                self.main_logger.info("🔍 执行健康检查...")
                
                # 检查每个账户的健康状态
                for account_id, account in list(self.active_accounts.items()):
                    if not account.is_healthy():
                        self.main_logger.warning(f"⚠️ 账户 {account_id} 健康检查失败，尝试重启...")
                        
                        if self.accounts_config['global_settings']['restart_on_error']:
                            self.stop_account(account_id)
                            time.sleep(5)
                            self.start_account(account_id)
                
                self.main_logger.info("✅ 健康检查完成")
                self.performance_reporter.maybe_send_reports(self.active_accounts)
                
            except Exception as e:
                self.main_logger.error(f"❌ 健康检查出错: {e}")
    
    def run(self):
        """运行多账户管理器"""
        try:
            # 启动所有账户
            self.start_all_accounts()
            
            if not self.active_accounts:
                self.main_logger.error("❌ 没有活跃的账户，退出")
                return
            
            # 启动健康检查线程
            health_thread = threading.Thread(target=self.health_check, daemon=True)
            health_thread.start()
            
            # 主循环
            self.main_logger.info("🎯 多账户交易系统运行中...")
            
            while self.running:
                time.sleep(1)
                
                # 检查是否有账户异常退出
                for account_id, account in list(self.active_accounts.items()):
                    if not account.is_running():
                        self.main_logger.warning(f"⚠️ 账户 {account_id} 异常退出")
                        
                        if self.accounts_config['global_settings']['restart_on_error']:
                            self.main_logger.info(f"🔄 重启账户 {account_id}...")
                            self.stop_account(account_id)
                            time.sleep(5)
                            self.start_account(account_id)
                
        except KeyboardInterrupt:
            self.main_logger.info("👋 收到中断信号，正在关闭...")
        except Exception as e:
            self.main_logger.error(f"❌ 运行出错: {e}")
        finally:
            self.stop_all_accounts()


class TradingAccount:
    """单个交易账户"""
    
    def __init__(self, account_id: str, config: dict, main_logger):
        self.account_id = account_id
        self.config = config
        self.main_logger = main_logger
        self.logger = self.setup_account_logger()
        self.exchange = None
        self.running = False
        self.thread = None
        self.strategy_state: Optional[StrategyState] = None
        self.telegram_runtime: Dict[str, Optional[str]] | None = None
        
        # 交易相关
        self.price_history = {sym['symbol']: [] for sym in config['config']['symbols']}
        self.last_analysis_time = {}

    def _resolve_env_value(self, placeholder: Optional[str]) -> Optional[str]:
        """解析环境变量占位符用于账户级配置"""
        if not placeholder:
            return None
        key = placeholder.strip('${}')
        value = os.getenv(key)
        if value is None and placeholder == key:
            return placeholder
        return value

    def _build_telegram_runtime_config(self) -> Dict[str, Optional[str]]:
        """解析账户 Telegram 设置"""
        tele_cfg = self.config.get('telegram', {})
        if not tele_cfg.get('enabled', False):
            return {'enabled': False}

        bot_token = self._resolve_env_value(tele_cfg.get('bot_token'))
        chat_id = self._resolve_env_value(tele_cfg.get('chat_id'))

        if not bot_token or not chat_id:
            self.logger.warning(f"[{self.account_id}] Telegram配置不完整，已禁用通知")
            return {'enabled': False}

        return {
            'enabled': True,
            'bot_token': bot_token,
            'chat_id': chat_id,
        }

    def setup_account_logger(self):
        """设置账户专用日志"""
        logger = logging.getLogger(f'trading_account_{self.account_id}')
        logger.setLevel(getattr(logging, self.config['logging']['level']))
        
        # 清除现有处理器
        logger.handlers.clear()
        
        # 文件处理器
        file_handler = logging.handlers.RotatingFileHandler(
            f'logs/{self.config["logging"]["file_prefix"]}_trading.log',
            maxBytes=10*1024*1024,  # 10MB
            backupCount=5,
            encoding='utf-8'
        )
        file_handler.setLevel(getattr(logging, self.config['logging']['level']))
        
        # 控制台处理器
        console_handler = logging.StreamHandler()
        console_handler.setLevel(logging.INFO)
        
        # 格式化
        formatter = logging.Formatter(
            f'%(asctime)s - [{self.account_id}] - %(levelname)s - %(message)s'
        )
        file_handler.setFormatter(formatter)
        console_handler.setFormatter(formatter)
        
        logger.addHandler(file_handler)
        logger.addHandler(console_handler)
        
        return logger
    
    def init_exchange(self):
        """初始化交易所"""
        try:
            # 获取环境变量
            api_key = self._resolve_env_value(self.config.get('api_key'))
            secret_key = self._resolve_env_value(self.config.get('secret_key'))
            passphrase = self._resolve_env_value(self.config.get('passphrase'))
            
            if not all([api_key, secret_key, passphrase]):
                self.logger.error("❌ 缺少必要的API密钥")
                return False
            
            self.exchange = ccxt.okx({
                'apiKey': api_key,
                'secret': secret_key,
                'password': passphrase,
                'sandbox': self.config['sandbox'],
                'enableRateLimit': True,
            })
            
            # 设置沙盒模式
            if self.config['sandbox']:
                self.exchange.set_sandbox_mode(True)
            
            # 测试连接
            balance = self.exchange.fetch_balance()
            self.logger.info(f"✅ 交易所初始化成功 (沙盒模式: {self.config['sandbox']})")
            return True
            
        except Exception as e:
            self.logger.error(f"❌ 交易所初始化失败: {e}")
            return False
    
    def send_telegram_notification(self, message: str, message_type: str = "info"):
        """发送Telegram通知"""
        if not self.telegram_runtime or not self.telegram_runtime.get('enabled'):
            return
        
        try:
            # 添加账户标识
            account_name = self.config['name']
            formatted_message = f"🤖 [{account_name}]\n{message}"
            send_telegram_message(
                formatted_message,
                parse_mode='Markdown',
                bot_token=self.telegram_runtime.get('bot_token'),
                chat_id=self.telegram_runtime.get('chat_id')
            )
            
        except Exception as e:
            self.logger.error(f"❌ 发送Telegram通知失败: {e}")
    
    def analyze_and_trade(self):
        """分析市场并执行交易"""
        if not self.strategy_state:
            self.logger.error(f"[{self.account_id}] 策略状态未初始化，跳过本轮分析")
            return

        try:
            self.strategy_state.exchange = self.exchange
            self.strategy_state.telegram_config = self.telegram_runtime or {'enabled': False}
            
            # 获取策略类型
            strategy_type = self.config.get('strategy', 'original')
            self.logger.info(f"[{self.account_id}] 使用策略: {strategy_type}")
            
            for symbol_config in self.strategy_state.trade_config['symbols']:
                symbol = symbol_config['symbol']

                # 根据策略类型获取市场数据
                if strategy_type == 'flight':
                    # 为Flight策略初始化专用交易所
                    try:
                        from flight_strategy import init_flight_exchange, get_flight_ohlcv_data
                        flight_exchange = init_flight_exchange(use_demo=self.config['sandbox'])
                        if not flight_exchange:
                            self.logger.warning(f"⚠️ {symbol} Flight策略交易所初始化失败，跳过分析")
                            continue
                        
                        # 临时设置全局交易所
                        import flight_strategy
                        original_exchange = getattr(flight_strategy, 'flight_exchange', None)
                        flight_strategy.flight_exchange = flight_exchange
                        
                        market_data = get_flight_ohlcv_data(symbol)
                        
                        # 恢复原始交易所
                        flight_strategy.flight_exchange = original_exchange
                        
                        if not market_data:
                            self.logger.warning(f"⚠️ {symbol} Flight策略数据不足，跳过分析")
                            continue
                            
                    except Exception as e:
                        self.logger.error(f"❌ {symbol} Flight策略数据获取失败: {e}")
                        continue
                else:
                    market_data = get_ohlcv_enhanced(
                        symbol,
                        state=self.strategy_state,
                    )

                    if not market_data or not market_data.get('kline_data'):
                        self.logger.warning(f"⚠️ {symbol} 数据不足，跳过分析")
                        continue

                # 更新价格历史
                try:
                    if strategy_type == 'flight':
                        closes = market_data['full_data']['close'].tolist()
                    else:
                        closes = market_data['full_data']['close'].tolist()
                    self.price_history[symbol] = closes
                    self.strategy_state.price_history[symbol] = closes
                except Exception:
                    pass

                # 根据策略类型进行分析
                if strategy_type == 'flight':
                    signal_data = analyze_with_flight(market_data, symbol)
                else:
                    signal_data = analyze_with_deepseek(
                        market_data,
                        symbol,
                        state=self.strategy_state,
                    )

                if not signal_data:
                    self.logger.warning(f"[{self.account_id}] {symbol} 未生成信号")
                    continue

                action = signal_data.get('signal', 'HOLD').upper()
                confidence = signal_data.get('confidence', 'UNKNOWN')
                
                # Flight策略的额外信息
                strategy_used = signal_data.get('strategy_used', 'N/A') if strategy_type == 'flight' else 'N/A'
                risk_reward = signal_data.get('risk_reward_ratio', 'N/A') if strategy_type == 'flight' else 'N/A'

                log_msg = f"[{self.account_id}] {symbol} 信号: {action} / 信心: {confidence}"
                if strategy_type == 'flight':
                    log_msg += f" / 策略: {strategy_used} / 盈亏比: {risk_reward}"
                self.logger.info(log_msg)

                # 执行交易
                if strategy_type == 'flight':
                    # Flight策略执行实际交易，使用AI自动分配的数量
                    if action in ['BUY', 'SELL']:
                        # 计算AI自动分配的交易数量
                        try:
                            # 获取账户余额
                            balance = self.exchange.fetch_balance()
                            usdt_balance = balance['USDT']['free'] if 'USDT' in balance else 1000  # 默认1000 USDT
                            
                            # 使用Flight策略的AI仓位计算
                            from flight_strategy import calculate_flight_position_size
                            ai_amount = calculate_flight_position_size(
                                symbol=symbol,
                                account_balance=usdt_balance,
                                leverage=self.strategy_state.trade_config.get('leverage', 20),
                                position_size_ratio=self.strategy_state.trade_config.get('position_size_ratio', 0.01),
                                confidence=confidence
                            )
                            
                            # 创建symbol_config用于交易执行
                            symbol_config_with_ai = {
                                'symbol': symbol,
                                'amount': ai_amount
                            }
                            
                            # 执行交易
                            trade_result = execute_trade(
                                signal_data,
                                market_data,
                                symbol_config_with_ai,
                                state=self.strategy_state,
                                telegram_config=self.telegram_runtime or {},
                                logger=self.logger
                            )
                            
                            if trade_result.get('executed'):
                                executed_amount = trade_result.get('amount')
                                operation = trade_result.get('operation', '')
                                self.send_telegram_notification(
                                    f"🚀 Flight策略交易执行\n"
                                    f"📈 {symbol} {action}\n"
                                    f"🎯 策略: {strategy_used}\n"
                                    f"🟢 信心: {confidence}\n"
                                    f"💰 盈亏比: {risk_reward}\n"
                                    f"📊 数量: {executed_amount}\n"
                                    f"📍 止损: ${signal_data.get('stop_loss', 0):,.2f}\n"
                                    f"🎯 止盈: ${signal_data.get('take_profit', 0):,.2f}\n"
                                    f"📝 理由: {signal_data.get('reason', '无')}\n"
                                    f"🤖 AI分配数量: {ai_amount}",
                                    "trade"
                                )
                            else:
                                reason = trade_result.get('reason')
                                self.logger.info(f"[{self.account_id}] {symbol} Flight策略未执行交易，原因: {reason}")
                                
                        except Exception as e:
                            self.logger.error(f"[{self.account_id}] {symbol} Flight策略交易执行失败: {e}")
                            # 发送通知但不执行交易
                            self.send_telegram_notification(
                                f"🚀 Flight策略信号\n"
                                f"📈 {symbol} {action}\n"
                                f"🎯 策略: {strategy_used}\n"
                                f"🟢 信心: {confidence}\n"
                                f"💰 盈亏比: {risk_reward}\n"
                                f"📍 止损: ${signal_data.get('stop_loss', 0):,.2f}\n"
                                f"🎯 止盈: ${signal_data.get('take_profit', 0):,.2f}\n"
                                f"📝 理由: {signal_data.get('reason', '无')}\n"
                                f"⚠️ 交易执行失败: {str(e)}",
                                "trade"
                            )
                    else:
                        self.logger.info(f"[{self.account_id}] {symbol} Flight策略观望信号")
                else:
                    # 原有策略执行实际交易
                    trade_result = execute_trade(
                        signal_data,
                        market_data,
                        symbol_config,
                        state=self.strategy_state,
                        telegram_config=self.telegram_runtime or {},
                        logger=self.logger
                    )

                    if trade_result.get('executed'):
                        executed_amount = trade_result.get('amount')
                        operation = trade_result.get('operation', '')
                        self.send_telegram_notification(
                            f"📈 {symbol} {action} 已执行\n"
                            f"数量: {executed_amount}\n"
                            f"操作: {operation}\n"
                            f"信心: {confidence}",
                            "trade"
                        )
                    else:
                        reason = trade_result.get('reason')
                        if reason not in {'low_confidence', 'hold'}:
                            self.logger.info(
                                f"[{self.account_id}] {symbol} 未执行交易，原因: {reason}"
                            )

                # 记录分析时间
                self.last_analysis_time[symbol] = datetime.now()
                
        except Exception as e:
            self.logger.error(f"❌ 分析交易出错: {e}")
            self.send_telegram_notification(f"❌ 交易分析出错: {e}", "error")

    def _get_loop_interval(self) -> int:
        try:
            timeframe = (self.strategy_state.trade_config.get('timeframe', '15m')
                         if self.strategy_state else '15m')
            unit = timeframe[-1]
            value = int(timeframe[:-1])
            unit_map = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}
            return max(value * unit_map.get(unit, 60), 30)
        except Exception:
            return 900

    def trading_loop(self):
        """交易主循环"""
        self.logger.info(f"🎯 开始交易循环 - {self.config['name']}")
        
        while self.running:
            try:
                # 分析并交易
                self.analyze_and_trade()
                
                # 等待下一个周期
                time.sleep(self._get_loop_interval())
                
            except Exception as e:
                self.logger.error(f"❌ 交易循环出错: {e}")
                time.sleep(60)  # 出错后等待1分钟再重试
    
    def start(self) -> bool:
        """启动账户"""
        try:
            # 初始化交易所
            if not self.init_exchange():
                return False
            
            self.telegram_runtime = self._build_telegram_runtime_config()
            self.strategy_state = create_strategy_state(
                trade_config=self.config['config'],
                exchange_instance=self.exchange,
                telegram_config=self.telegram_runtime,
                sandbox=self.config.get('sandbox', True),
                account_id=self.account_id,
            )
            active_risk = self.strategy_state.trade_config.get('risk_profile', 'balanced')
            self.logger.info(f"[{self.account_id}] 风险档位: {active_risk}")
            
            # 发送启动通知
            self.send_telegram_notification(
                f"🚀 账户启动成功\n"
                f"模式: {'模拟盘' if self.config['sandbox'] else '实盘'}\n"
                f"交易对: {len(self.config['config']['symbols'])} 个\n"
                f"杠杆: {self.strategy_state.trade_config.get('leverage', self.config['config'].get('leverage'))}x\n"
                f"风险档: {active_risk}",
                "startup"
            )
            
            # 启动交易线程
            self.running = True
            self.thread = threading.Thread(target=self.trading_loop, daemon=True)
            self.thread.start()
            
            return True
            
        except Exception as e:
            self.logger.error(f"❌ 启动账户失败: {e}")
            return False
    
    def stop(self):
        """停止账户"""
        self.running = False
        
        if self.thread and self.thread.is_alive():
            self.thread.join(timeout=10)
        
        # 发送停止通知
        self.send_telegram_notification("🛑 账户已停止", "shutdown")
        
        self.logger.info(f"🛑 账户 {self.account_id} 已停止")
    
    def is_running(self) -> bool:
        """检查是否正在运行"""
        return self.running and self.thread and self.thread.is_alive()
    
    def is_healthy(self) -> bool:
        """健康检查"""
        try:
            # 检查交易所连接
            balance = self.exchange.fetch_balance()
            return True
        except Exception as e:
            self.logger.warning(f"⚠️ 健康检查失败: {e}")
        return False


class PerformanceReporter:
    def __init__(self, logger):
        self.logger = logger
        now = datetime.now()
        self.daily_anchor = now.date()
        iso = now.isocalendar()
        self.week_anchor = (iso[0], iso[1])
        self.month_anchor = (now.year, now.month)

    def maybe_send_reports(self, accounts: Dict[str, 'TradingAccount']):
        if not accounts:
            return

        now = datetime.now()
        self._handle_daily(now, accounts)
        self._handle_weekly(now, accounts)
        self._handle_monthly(now, accounts)

    def _handle_daily(self, now, accounts):
        if now.date() == self.daily_anchor:
            return
        target_date = now.date() - timedelta(days=1)
        self._dispatch_report(
            'daily',
            datetime.combine(target_date, dt_time.min),
            datetime.combine(target_date, dt_time.min) + timedelta(days=1),
            f"日终 {target_date.isoformat()}",
            accounts
        )
        self.daily_anchor = now.date()

    def _handle_weekly(self, now, accounts):
        iso = now.isocalendar()
        current_week = (iso[0], iso[1])
        if current_week == self.week_anchor:
            return
        year, week = self.week_anchor
        try:
            week_start = datetime.fromisocalendar(year, week, 1)
        except ValueError:
            week_start = now - timedelta(days=7)
        week_end = week_start + timedelta(days=7)
        self._dispatch_report(
            'weekly',
            week_start,
            week_end,
            f"周度 {year}-W{week}",
            accounts
        )
        self.week_anchor = current_week

    def _handle_monthly(self, now, accounts):
        current_month = (now.year, now.month)
        if current_month == self.month_anchor:
            return
        year, month = self.month_anchor
        start = datetime(year, month, 1)
        if month == 12:
            end = datetime(year + 1, 1, 1)
        else:
            end = datetime(year, month + 1, 1)
        self._dispatch_report(
            'monthly',
            start,
            end,
            f"月度 {year}-{month:02d}",
            accounts
        )
        self.month_anchor = current_month

    def _dispatch_report(self, period, start_dt, end_dt, label, accounts):
        events = self._load_events(start_dt, end_dt)
        if not events:
            return
        stats_by_account = self._summarize(events)
        for account_id, stats in stats_by_account.items():
            account = accounts.get(account_id)
            if account is None:
                continue
            if stats['trades'] == 0:
                continue
            win_rate = (stats['wins'] / stats['trades']) * 100 if stats['trades'] else 0
            roi = (stats['pnl'] / stats['margin']) * 100 if stats['margin'] else 0
            message = (
                f"📊 {label} 收益报告\n"
                f"账户: {account.config['name']}\n"
                f"收益: {stats['pnl']:+.2f} USDT | ROI: {roi:.2f}%\n"
                f"胜率: {win_rate:.1f}% ({stats['wins']}/{stats['trades']})\n"
                f"交易: {stats['trades']} 次 | 手续费: {stats['fees']:.2f} USDT"
            )
            account.send_telegram_notification(message, "report")

    def _load_events(self, start_dt, end_dt):
        if not os.path.exists(TRADE_HISTORY_FILE):
            return []
        results = []
        try:
            with open(TRADE_HISTORY_FILE, 'r', encoding='utf-8') as f:
                for line in f:
                    line = line.strip()
                    if not line:
                        continue
                    try:
                        event = json.loads(line)
                        ts = datetime.fromisoformat(event.get('timestamp'))
                        if start_dt <= ts < end_dt:
                            results.append(event)
                    except Exception:
                        continue
        except Exception as exc:
            self.logger.warning(f"读取交易历史失败: {exc}")
        return results

    @staticmethod
    def _summarize(events):
        stats = {}
        for event in events:
            account_id = event.get('account_id') or 'unknown'
            entry = stats.setdefault(account_id, {
                'trades': 0,
                'wins': 0,
                'pnl': 0.0,
                'fees': 0.0,
                'margin': 0.0,
            })
            entry['trades'] += 1
            pnl = float(event.get('pnl') or 0)
            if pnl > 0:
                entry['wins'] += 1
            entry['pnl'] += pnl
            entry['fees'] += float(event.get('fee') or 0)
            entry['margin'] += abs(float(event.get('margin_used') or 0))
        return stats

def main():
    """主函数"""
    print("🚀 多账户交易机器人启动中...")
    
    # 检查配置文件
    if not os.path.exists("accounts_config.json"):
        print("❌ 配置文件 accounts_config.json 不存在")
        sys.exit(1)
    
    # 创建并运行账户管理器
    manager = AccountManager()
    manager.run()


if __name__ == "__main__":
    main()
